/**************************************************************************//**
 * @file     startup_stm32f103c8tx.S
 * @brief    bootloader工程启动汇编文件
 * @version  V0.0.1
 * @date     2020-02-01
 ******************************************************************************/

/* 如果有include文件，则需要把文件后缀命名为大写的.S，这样才会做预处理 */

  .syntax unified   @ 表示使用了统一汇编语言语法
  .cpu cortex-m3    @ 表示用于M3架构
  .fpu softvfp      @ 不使用硬件浮点功能，因为STM32 M3没有硬件浮点模块VFP
  .thumb            @ 采用的指令集

.global g_pfnVectors      @ global使得g_pfnVectors可以被其他目标文件使用
.global Default_Handler

/* 这些变量在ld文件中定义，用来指定各个段的起始和结束地址 */
/* start address for the initialization values of the .data section. defined in linker script */
.word _sidata   /* DATA段在Flash中的起始地址，用户保存初始化了的全局变量 */
/* start address for the .data section. defined in linker script */
.word _sdata    /* DATA段在SRAM中的起始地址 */
/* end address for the .data section. defined in linker script */
.word _edata    /* DATA段的结束地址 */
/* start address for the .bss section. defined in linker script */
.word _sbss     /* BSS段的起始地址，保持了未初始化的全局变量 */
/* end address for the .bss section. defined in linker script */
.word _ebss     /* BSS段的结束地址 */

.equ  BootRAM, 0xF108F85F @ 这里跟c中的宏定义类似，即 #define BootRAM 0xF108F85F,不参与编译
/**
 * @brief  This is the code that gets called when the processor first
 *          starts execution following a reset event. Only the absolutely
 *          necessary set is performed, after which the application
 *          supplied main() routine is called.
 * @param  None
 * @retval : None
*/

  .section .text.Reset_Handler
  .weak Reset_Handler
  .type Reset_Handler, %function
Reset_Handler:

/* Copy the data segment initializers from flash to SRAM */
/* 首先从Flash中拷贝DATA段，即_sdata和_edata之间的数据到SRAM中 */
  movs r1, #0         @ 将立即数0赋值给r1寄存器，其作为offset使用
  b LoopCopyDataInit

CopyDataInit:
  ldr r3, =_sidata    @ 从存储器中将_sidata加载到寄存器r3中，
  ldr r3, [r3, r1]    @ 从地址r3 + r1处读取一个字（32bit）到r3中，即从FLASH中的DATA段中读一个DWORD数据
  str r3, [r0, r1]    @ 把寄存器r3的值存储到存储器中地址为r0+r1地址处，即将数据保存到SRAM段中的DATA段
  adds r1, r1, #4     @ r1偏移加4，即准备取下一个DWORD

LoopCopyDataInit:
  ldr r0, =_sdata     @ 将DATA段在SRAM中的起始地址赋给r0
  ldr r3, =_edata     @ 将DATA段在SRAM中的结束地址赋给r3
  adds r2, r0, r1     @ r2 = r0(起始地址) + r1(偏移值)，即当前已经拷贝的数据位置
  cmp r2, r3          @ 判断r2是否等于r3，即是否拷贝完成
  bcc CopyDataInit    @ 如果没有拷贝完成，则继续跳转到CopyDataInit进行拷贝

/* BSS段保存的是未初始化的全局变量，这里默认将其全部清零 */
  ldr r2, =_sbss      @ 将BSS段的起始地址赋给r2
  b LoopFillZerobss   @ 跳转到LoopFillZerobss执行清零
/* Zero fill the bss segment. */
FillZerobss:
  movs r3, #0         @ 将立即数0赋给寄存器r3，movs中的s说明会影响CPSR状态位
  str r3, [r2], #4    @ 将寄存器r3的值存储到地址为r2的地址处，完成后再将r2的值加4

LoopFillZerobss:
  ldr r3, = _ebss     @ 将BSS段的结束地址赋给r3
  cmp r2, r3          @ 比较r2和r3的值，判断是否拷贝完成，r2保存当前已经清零的位置
  bcc FillZerobss     @ 如果不相等，说明没有清零完全部空间，跳到FillZerobss继续清零

/* Call the clock system intitialization function.*/
/* 在正式跳转到main函数前，先进行必要的系统初始化 */
  bl MAIN_SystemInit
  bl SYS_InitBeforeMain
/* Call static constructors */
/* libc标准，里面会执行ld链接文件里preinit_array、init_array、fini_array段中的函数 */
  bl __libc_init_array
/* Call the application's entry point.*/
  bl Main  @ 跳转到真正的C语言函数入口，一般里面是个死循环
  bx lr
.size Reset_Handler, .-Reset_Handler

/**
 * @brief  This is the code that gets called when the processor receives an
 *         unexpected interrupt.  This simply enters an infinite loop, preserving
 *         the system state for examination by a debugger.
 *
 * @param  None
 * @retval : None
*/
/* 
 * 死循环函数，默认异常和中断都会默认跳到这里，用户可以重新实现中断处理函数
 * .section 语法格式为 .section name [, "flags"[, @type[,flag_specific_arguments]]]
 * 官方参考：http://sourceware.org/binutils/docs-2.22/as/Section.html#Section@progbits
 * flags为 "ax" 表示需要分配内存并且可执行，除此外还有 ”A”=分配内存，“WA”=分配内存并且可修改。
 * arguments为 progbits 表示是程序数据，如.text、.data、.rodata，除此外还有：
 *   ”NULL”：未使用，如段表的第一个空段。
 *   “REL”：重定位表，如.rel.text。
 *   “NOBITS”：暂时没有数据的程序空间，如.bss。
 *   “STRTAB”：字符串表，如.strtab、.shstrtab。
 *   “SYMTAB”：符号表，如.symtab。
 */
    .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
  b Infinite_Loop
  .size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex M3.  Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
  .section .isr_vector,"a",%progbits  @ 定义中断向量表的数据段
  .type g_pfnVectors, %object
  .size g_pfnVectors, .-g_pfnVectors

/* 默认中断向量表，和枚举 IRQn_Type 对应 */
g_pfnVectors:
  .word _estack   /* Cortex-M3内核规定，起始地址必须存放MSP栈顶指针，指令从第2个dword开始取，即下面的Reset_Handler
                     TBA 这里并没有使用ld里面设置的_user_heap_stack段作为栈顶？另外堆是怎么设置的？ */
  .word Reset_Handler       /* -15 优先级固定等于-3 */
  .word NMI_Handler         /* -14 优先级固定等于-2 */
  .word HardFault_Handler   /* -13 优先级固定等于-1 */
  .word MemManage_Handler   /* -12 */
  .word BusFault_Handler    /* -11 */
  .word UsageFault_Handler  /* -10 */
  .word 0
  .word 0
  .word 0
  .word 0
  .word SVC_Handler         /* -5 */
  .word DebugMon_Handler    /* -4 */
  .word 0
  .word PendSV_Handler      /* -2 */
  .word SysTick_Handler     /* -1 */
  .word WWDG_IRQHandler     /* 0 */
  .word PVD_IRQHandler
  .word TAMPER_IRQHandler
  .word RTC_IRQHandler
  .word FLASH_IRQHandler
  .word RCC_IRQHandler
  .word EXTI0_IRQHandler
  .word EXTI1_IRQHandler
  .word EXTI2_IRQHandler
  .word EXTI3_IRQHandler
  .word EXTI4_IRQHandler    /* 10 */
  .word DMA1_Channel1_IRQHandler
  .word DMA1_Channel2_IRQHandler
  .word DMA1_Channel3_IRQHandler
  .word DMA1_Channel4_IRQHandler
  .word DMA1_Channel5_IRQHandler
  .word DMA1_Channel6_IRQHandler
  .word DMA1_Channel7_IRQHandler
  .word ADC1_2_IRQHandler
  .word USB_HP_CAN1_TX_IRQHandler
  .word USB_LP_CAN1_RX0_IRQHandler  /* 20 */
  .word CAN1_RX1_IRQHandler
  .word CAN1_SCE_IRQHandler
  .word EXTI9_5_IRQHandler
  .word TIM1_BRK_IRQHandler
  .word TIM1_UP_IRQHandler
  .word TIM1_TRG_COM_IRQHandler
  .word TIM1_CC_IRQHandler
  .word TIM2_IRQHandler
  .word TIM3_IRQHandler
  .word TIM4_IRQHandler     /* 30 */
  .word I2C1_EV_IRQHandler
  .word I2C1_ER_IRQHandler
  .word I2C2_EV_IRQHandler
  .word I2C2_ER_IRQHandler
  .word SPI1_IRQHandler
  .word SPI2_IRQHandler
  .word USART1_IRQHandler
  .word USART2_IRQHandler
  .word USART3_IRQHandler
  .word EXTI15_10_IRQHandler  /* 40 */
  .word RTC_Alarm_IRQHandler
  .word USBWakeUp_IRQHandler
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word 0
  .word BootRAM   /* 50 0x108. This is for boot in RAM mode for STM32F10x Medium Density devices.
                     这个是专门为stm32f10系列中容量系列设备的boot中的RAM模式准备的 */

/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
  /* 下面都是弱定义，用户可以自行定义重名函数，这样将会覆盖掉下面的函数 */
  .weak NMI_Handler  @定义一个弱别名NMI_Handler
  .thumb_set NMI_Handler,Default_Handler    @ 如果这个不重写这个弱别名，那么默认执行Default_Handler，反之这执行重写过的 NMI_Handler

  .weak HardFault_Handler
  .thumb_set HardFault_Handler,Default_Handler

  .weak MemManage_Handler
  .thumb_set MemManage_Handler,Default_Handler

  .weak BusFault_Handler
  .thumb_set BusFault_Handler,Default_Handler

  .weak UsageFault_Handler
  .thumb_set UsageFault_Handler,Default_Handler

  .weak SVC_Handler
  .thumb_set SVC_Handler,Default_Handler

  .weak DebugMon_Handler
  .thumb_set DebugMon_Handler,Default_Handler

  .weak PendSV_Handler
  .thumb_set PendSV_Handler,Default_Handler

  .weak SysTick_Handler
  .thumb_set SysTick_Handler,Default_Handler

  .weak WWDG_IRQHandler
  .thumb_set WWDG_IRQHandler,Default_Handler

  .weak PVD_IRQHandler
  .thumb_set PVD_IRQHandler,Default_Handler

  .weak TAMPER_IRQHandler
  .thumb_set TAMPER_IRQHandler,Default_Handler

  .weak RTC_IRQHandler
  .thumb_set RTC_IRQHandler,Default_Handler

  .weak FLASH_IRQHandler
  .thumb_set FLASH_IRQHandler,Default_Handler

  .weak RCC_IRQHandler
  .thumb_set RCC_IRQHandler,Default_Handler

  .weak EXTI0_IRQHandler
  .thumb_set EXTI0_IRQHandler,Default_Handler

  .weak EXTI1_IRQHandler
  .thumb_set EXTI1_IRQHandler,Default_Handler

  .weak EXTI2_IRQHandler
  .thumb_set EXTI2_IRQHandler,Default_Handler

  .weak EXTI3_IRQHandler
  .thumb_set EXTI3_IRQHandler,Default_Handler

  .weak EXTI4_IRQHandler
  .thumb_set EXTI4_IRQHandler,Default_Handler

  .weak DMA1_Channel1_IRQHandler
  .thumb_set DMA1_Channel1_IRQHandler,Default_Handler

  .weak DMA1_Channel2_IRQHandler
  .thumb_set DMA1_Channel2_IRQHandler,Default_Handler

  .weak DMA1_Channel3_IRQHandler
  .thumb_set DMA1_Channel3_IRQHandler,Default_Handler

  .weak DMA1_Channel4_IRQHandler
  .thumb_set DMA1_Channel4_IRQHandler,Default_Handler

  .weak DMA1_Channel5_IRQHandler
  .thumb_set DMA1_Channel5_IRQHandler,Default_Handler

  .weak DMA1_Channel6_IRQHandler
  .thumb_set DMA1_Channel6_IRQHandler,Default_Handler

  .weak DMA1_Channel7_IRQHandler
  .thumb_set DMA1_Channel7_IRQHandler,Default_Handler

  .weak ADC1_2_IRQHandler
  .thumb_set ADC1_2_IRQHandler,Default_Handler

  .weak USB_HP_CAN1_TX_IRQHandler
  .thumb_set USB_HP_CAN1_TX_IRQHandler,Default_Handler

  .weak USB_LP_CAN1_RX0_IRQHandler
  .thumb_set USB_LP_CAN1_RX0_IRQHandler,Default_Handler

  .weak CAN1_RX1_IRQHandler
  .thumb_set CAN1_RX1_IRQHandler,Default_Handler

  .weak CAN1_SCE_IRQHandler
  .thumb_set CAN1_SCE_IRQHandler,Default_Handler

  .weak EXTI9_5_IRQHandler
  .thumb_set EXTI9_5_IRQHandler,Default_Handler

  .weak TIM1_BRK_IRQHandler
  .thumb_set TIM1_BRK_IRQHandler,Default_Handler

  .weak TIM1_UP_IRQHandler
  .thumb_set TIM1_UP_IRQHandler,Default_Handler

  .weak TIM1_TRG_COM_IRQHandler
  .thumb_set TIM1_TRG_COM_IRQHandler,Default_Handler

  .weak TIM1_CC_IRQHandler
  .thumb_set TIM1_CC_IRQHandler,Default_Handler

  .weak TIM2_IRQHandler
  .thumb_set TIM2_IRQHandler,Default_Handler

  .weak TIM3_IRQHandler
  .thumb_set TIM3_IRQHandler,Default_Handler

  .weak TIM4_IRQHandler
  .thumb_set TIM4_IRQHandler,Default_Handler

  .weak I2C1_EV_IRQHandler
  .thumb_set I2C1_EV_IRQHandler,Default_Handler

  .weak I2C1_ER_IRQHandler
  .thumb_set I2C1_ER_IRQHandler,Default_Handler

  .weak I2C2_EV_IRQHandler
  .thumb_set I2C2_EV_IRQHandler,Default_Handler

  .weak I2C2_ER_IRQHandler
  .thumb_set I2C2_ER_IRQHandler,Default_Handler

  .weak SPI1_IRQHandler
  .thumb_set SPI1_IRQHandler,Default_Handler

  .weak SPI2_IRQHandler
  .thumb_set SPI2_IRQHandler,Default_Handler

  .weak USART1_IRQHandler
  .thumb_set USART1_IRQHandler,Default_Handler

  .weak USART2_IRQHandler
  .thumb_set USART2_IRQHandler,Default_Handler

  .weak USART3_IRQHandler
  .thumb_set USART3_IRQHandler,Default_Handler

  .weak EXTI15_10_IRQHandler
  .thumb_set EXTI15_10_IRQHandler,Default_Handler

  .weak RTC_Alarm_IRQHandler
  .thumb_set RTC_Alarm_IRQHandler,Default_Handler

  .weak USBWakeUp_IRQHandler
  .thumb_set USBWakeUp_IRQHandler,Default_Handler

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

